#pragma once

#include "BaseNetworkChannel.h"
#include <asio.hpp>

namespace SeanNetwork {

/**
 * @brief KCP channel implementation.
 * 
 * Provides KCP-specific network channel implementation by extending
 * the BaseNetworkChannel template methods.
 */
class KcpChannel : public BaseNetworkChannel {
public:
    KcpChannel(asio::io_context& ioContext);
    ~KcpChannel() override;
    
    // INetworkChannel interface implementation
    bool Initialize() override;
    bool Connect(const std::string& host, uint16_t port) override;
    void Disconnect() override;
    bool SendMsg(std::shared_ptr<NetworkMessage> message) override;
    void SetMessageCallback(MessageReceiveCallback callback) override;
    void SetConnectionCallback(ConnectionStateCallback callback) override;
    ConnectionState GetConnectionState() const override;
    NetworkStats GetNetworkStats() const override;
    uint32_t GetLatency() const override;
    void Update() override;
    ChannelType GetChannelType() const override;
    
    // KCP specific methods
    void SetNodelay(bool nodelay, int interval, int resend, bool nc);
    void SetWindowSize(int sndwnd, int rcvwnd);
    void SetMtu(int mtu);
    void SetMinRto(int minrto);
    void SetFastResend(int fastresend);
    
    // 服务器端特有方法
    void SetupServerConnection(const asio::ip::udp::endpoint& clientEndpoint);
    void HandleReceivedData(const uint8_t* data, size_t length, const asio::ip::udp::endpoint& sender);
    
protected:
    // BaseNetworkChannel template methods implementation
    bool DoInitialize() override;
    bool DoConnect(const std::string& host, uint16_t port) override;
    void DoDisconnect() override;
    void DoSendMessage(std::shared_ptr<NetworkMessage> message) override;
    void DoUpdate() override;
    void StartReconnect() override;
    void SendKeepAlive() override;
    
    // Helper methods from base class
    void UpdateConnectionState(ConnectionState newState, const std::string& reason = "");
    void UpdateNetworkStats(uint64_t bytesSent, uint64_t bytesReceived, bool messageSent, bool messageReceived);
    void UpdateRtt(uint32_t rtt);
    uint32_t CalculateReconnectDelay() const;
    void HandleMessageAck(uint32_t messageId, bool success);
    
private:
    // KCP实例包装器
    class KcpSession {
    public:
        KcpSession();
        ~KcpSession();
        
        bool Create(uint32_t conv);
        void Release();
        
        bool IsCreated() const;
        bool Send(const uint8_t* data, int size);
        int Recv(uint8_t* data, int size);
        
        void Update(uint32_t current);
        uint32_t Check(uint32_t current);
        
        void SetOutput(std::function<int(const uint8_t*, int)> output);
        void SetNodelay(bool nodelay, int interval, int resend, bool nc);
        void SetWindowSize(int sndwnd, int rcvwnd);
        void SetMtu(int mtu);
        void SetMinRto(int minrto);
        void SetFastResend(int fastresend);
        
        uint32_t GetLatestRtt() const;
        void* GetKcpCb() const;
        
    private:
        void* m_KcpCb;  // KCP控制块指针
        std::function<int(const uint8_t*, int)> m_OutputCallback;
    };
    
    asio::ip::udp::socket m_Socket;
    asio::ip::udp::endpoint m_RemoteEndpoint;
    
    std::unique_ptr<KcpSession> m_KcpSession;
    uint32_t m_KcpConv;  // KCP会话ID
    
    std::vector<uint8_t> m_ReadBuffer;
    std::vector<uint8_t> m_RawReadBuffer;
    
    uint32_t m_UpdateInterval;  // KCP更新间隔（毫秒）
    uint32_t m_KeepAliveInterval;  // 心跳包间隔（毫秒）
    
    std::shared_ptr<asio::steady_timer> m_UpdateTimer;
    std::shared_ptr<asio::steady_timer> m_KeepAliveTimer;
    std::shared_ptr<asio::steady_timer> m_ReconnectTimer;
    
    std::atomic<bool> m_IsReceiving;  // 是否正在接收
    
    // KCP specific methods
    void StartReceive();
    void StartKcpUpdate();
    void HandleUdpReceive(const asio::error_code& ec, std::size_t bytes_transferred);
    void HandleKcpReceive();
    void SendNextMessage();
    
    // UDP output callback
    int UdpOutput(const uint8_t* data, int size);
};

} // namespace SeanNetwork
